package cn.xiaoke.fanxin.fanshe;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class Demo2 {

    public static void main(String[] args) throws NoSuchMethodException {
        soutMethodA();
        soutMethodB();
        soutMethodC();
        System.out.println();
    }

    private static void soutMethodA() throws NoSuchMethodException {
        final Method[] declaredMethods = A.class.getDeclaredMethods();
        final Method[] methods = A.class.getMethods();
        final Method test = A.class.getMethod("test", Object.class);
        final Class<?>[] parameterTypes = test.getParameterTypes();
        final Type[] genericParameterTypes = test.getGenericParameterTypes();
        System.out.println("genericParameterTypes[0].getClass() = " + genericParameterTypes[0].getClass());
        System.out.println(((TypeVariable) genericParameterTypes[0]).getName());
        System.out.println("===================");
    }

    private static void soutMethodB() throws NoSuchMethodException {
        final Class<B> bClass = B.class;
        final Method[] declaredMethods = bClass.getDeclaredMethods();
        final Method[] methods = bClass.getMethods();
        final Method test = bClass.getMethod("test", String.class);
        final Class<?>[] parameterTypes = test.getParameterTypes();
        final Type[] genericParameterTypes = test.getGenericParameterTypes();
        System.out.println("genericParameterTypes[0].getClass() = " + genericParameterTypes[0].getClass());
        System.out.println("genericParameterTypes[0] = " + genericParameterTypes[0]);
        System.out.println("===================");
    }

    private static void soutMethodC() throws NoSuchMethodException {
        final Method[] declaredMethods = C.class.getDeclaredMethods();
        final Method[] methods = C.class.getMethods();
        final Method test = C.class.getMethod("test", Collection.class);
        final Class<?>[] parameterTypes = test.getParameterTypes();
        final Type[] genericParameterTypes = test.getGenericParameterTypes();
        System.out.println("genericParameterTypes[0].getClass() = " + genericParameterTypes[0].getClass());
        System.out.println(genericParameterTypes[0].getTypeName());
        System.out.println("---------------");
        final Type actualTypeArgument = ((ParameterizedType) genericParameterTypes[0]).getActualTypeArguments()[0];
        System.out.println(actualTypeArgument);
        System.out.println("---------------");
        final Type actualTypeArgument2 = ((ParameterizedType) actualTypeArgument).getActualTypeArguments()[0];
        System.out.println(actualTypeArgument2);
        System.out.println("---------------");
        final Type actualTypeArgument3 = ((ParameterizedType) actualTypeArgument2).getActualTypeArguments()[0];
        System.out.println(actualTypeArgument3);
        System.out.println("---------------");
        System.out.println();
    }

    static class A<T> {

        public T test(T t) {

            return null;
        }
    }

    static class B extends A<String> {

        @Override
        public String test(String s) {
            return super.test(s);
        }
    }

    static class C extends A<Collection<List<ArrayList<String>>>> {

        @Override
        public Collection<List<ArrayList<String>>> test(Collection<List<ArrayList<String>>> strings) {
            return super.test(strings);
        }
    }
}
